/* IR protocols example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "sdkconfig.h"
#include "nvs_flash.h"
#include "esp_system.h"

#include "RCS_protocol.h"
#include "RCS_slave.h"
#include "RCS_btn.h"
#include "RCS_fire.h"
#include "RCS_nfc.h"
#include "RCS_ble_slave.h"
#include "RCS_led.h"

/////////////////////GLOBAL VARIABLE/////////////////////
extern rcs_slave_system_t rcsSystem;

QueueHandle_t xUploadDataQueue;
TaskHandle_t shockTaskHandle;
TaskHandle_t bleserverTaskHandle;
TaskHandle_t nfcTaskHandle;

/*
根据notify消息来判断哪个bit置1，其它置0
在led任务中，被击中事件响应结束以后把事件bit置0.
震动任务只能getbit
*/

static const char *SYS_TAG = "RCS_SYS";
static const char *SHOCK_TAG = "SHOCK_TAG";
static const char *LED_TAG = "LED_TAG";
static const char *BLE_TAG = "BLE_TAG";
static const char *IR_TAG = "IR_TAG";
static const char *NFC_TAG = "NFC_TAG";

/////////////////////TASK DECLAIRATION/////////////////////

static void ir_rx_task(void *arg);

static void ble_receive_server_task(void *arg);

static void led_task(void *arg);

static void shock_task(void *arg);

static void nfc_task(void *arg);

static void main_task(void *arg);

void app_main(void)
{
    // 按钮初始化
    btn_init();
    // 供电
    ESP_LOGI(SYS_TAG, "..........power_init............");
    power_init();
    /* Initialize NVS. */
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    game_event_init();
    // 电量查询初始化
    rcs_adc_battery_init();
    rcsSystem.device.battery = rcs_adc_battery_read();
    ESP_LOGI(SYS_TAG, "battery :%d.", rcsSystem.device.battery);
    xUploadDataQueue = xQueueCreate(5, ARMOR_UPL_PACK_MAX_LEN);
    xTaskCreate(main_task, "main_task", 1024 * 10, NULL, 11, NULL);
}

static void main_task(void *arg)
{
    vTaskDelay(pdMS_TO_TICKS(5000));
    // 灯光任务：
    xTaskCreate(led_task, "led_task", 1024 * 3, NULL, 8, NULL);

    // 蓝牙任务:
    xTaskCreate(ble_receive_server_task, "ble_receive_server_task", 1024 * 25, NULL, 12, &bleserverTaskHandle);

    // 红外任务：
    xTaskCreate(rcs_ir_rx_task, "ir_rx_task", 1024 * 10, NULL, 10, NULL);

    // 震动提示任务
    xTaskCreate(shock_task, "shock_task", 1024 * 3, NULL, 6, &shockTaskHandle);

    // nfc任务
    xTaskCreate(nfc_task, "nfc_task", 1024 * 5, NULL, 9, &nfcTaskHandle);

    ESP_LOGI(SYS_TAG, "[APP] Startup..");
    ESP_LOGI(SYS_TAG, "[APP] IDF version: %s", esp_get_idf_version());
    ESP_LOGI(SYS_TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
    vTaskDelay(pdMS_TO_TICKS(5000));
    register_btn();
    vTaskDelete(NULL);
    return;
}

static void ble_receive_server_task(void *arg)
{
    rcs_ble_init();
    ESP_LOGI(BLE_TAG, "ble_receive_server_task Startup..");

    rcs_start_advertise(rcsSystem.device.wait_new_master);
    // package
    uint8_t package[ARMOR_UPL_PACK_MAX_LEN];
    BaseType_t xStatus;
    while (1)
    {
        switch (rcsSystem.device.is_connect_master)
        {
        case DISCONNECT_BLE:
        {
            ESP_LOGI(BLE_TAG, "didn't connect, so Suspend ble_shoot_server_task ..");
            // 没连接上主机时，挂起自己，ble的fsm还能工作，等待连上server以后再恢复此任务
            rcs_stop_advertise();
            rcs_start_advertise(rcsSystem.device.wait_new_master);
            vTaskSuspend(NULL);
            break;
        }
        case INITING_BLE:
        {
            uint8_t pack_len = 0;
            uint8_t *package = make_verify_package(&pack_len);
            ESP_LOGE(BLE_TAG, "send VERTIFY package to MASTER");
            rcs_notify_client(package, pack_len);
            free(package);
            vTaskDelay(pdMS_TO_TICKS(1000));
            break;
        }
        case CONNECTED_BLE:
        {
            // 只要连接上了ble server,就把队列里的消息读取并发送，如果没连上也读取会浪费掉消息。
            xStatus = xQueueReceive(xUploadDataQueue, package, pdMS_TO_TICKS(500));
            if (xStatus == pdPASS)
            {
                uint16_t pack_len = package[2];
                rcs_notify_client(package, pack_len);
            }
            break;
        }
        default:
            break;
        }
    }
}

static void shock_task(void *arg)
{
    rcs_event_t *event;
    uint8_t dead_num = 0;
    bool state = false;
    shock_init();
    ESP_LOGI(SHOCK_TAG, "shock_task Startup..");
    while (1)
    {
        if (rcsSystem.game.start)
        {
            if (rcsSystem.game.player.living)
            {
                dead_num = 0;
                event = get_game_event_state();
                if (event->class == BE_HITTED)
                {
                    set_shock(true);
                    // ESP_LOGI(SHOCK_TAG, "be hit shocking");
                    vTaskDelay(pdMS_TO_TICKS(100));
                }
                else
                {
                    set_shock(false);
                    vTaskSuspend(NULL);
                }
            }
            else
            { // 死亡的时候保持1s间隔的震动
                if (dead_num >= 20)
                {
                    dead_num = 0;
                }
                state = (dead_num < 10) ? true : false;
                dead_num++;
                set_shock(state);
                // ESP_LOGI(SHOCK_TAG, "dead :%d", state);
                vTaskDelay(pdMS_TO_TICKS(100));
            }
        }
        else
        {
            dead_num = 0;
            // ESP_LOGE(SHOCK_TAG, "game no start, suspend shock_task");
            set_shock(false);
            vTaskSuspend(NULL);
        }
    }
}

#define EVENT_INTERVAL 100
#define ADVERTISING_INTERVAL 100

static void led_task(void *arg)
{
    rcs_event_t *event;
    uint8_t game_no_start_count = 0;
    uint8_t advertising_count = 0;
    uint8_t no_connect_count = 0;
    uint8_t low_battery_count = 0;
    led_t led_2 = {
        .state = true,
        .delay_time = 1000};
    led_t led_9 = {
        .state = 0,
        .delay_time = 1000};
    led_init();
    ESP_LOGI(LED_TAG, "led_task Startup..");
    while (1)
    {
        // 不想新开一个任务，就直接在灯光这里实时更新电池数据。
        rcsSystem.device.battery = rcs_adc_battery_read();
        if (rcsSystem.device.battery < LOW_BATTERY_THRESHOLD)
        {
            rcsSystem.device.low_batt = true;
        }
        else
        {
            rcsSystem.device.low_batt = false;
        }

        // 先判断有没有事件，如果有先执行事件的显示，没有事件再根据状态显示，只会有一种事件
        event = get_game_event_state();
        if (event->class)
        {
            led_2.state = (event->count % 2 == 0) ? true : false;
            led_2.delay_time = EVENT_INTERVAL;
            if (event->class == BE_HITTED ||
                event->class == REMOTE_COMM_EVENT)
            {
                led_9.state = (event->count % 2 == 0) ? true : false;
            }
            else
            {
                led_9.state = 0;
            }
            update_game_event();
        }
        else
        {
            if (rcsSystem.device.is_connect_master == CONNECTED_BLE)
            {
                if (rcsSystem.game.start)
                {
                    // 游戏开始
                    if (rcsSystem.game.player.living)
                    {
                        // 活着
                        // led_2.state = !(rcsSystem.game.player.team % 2);
                        //取消队伍为2时常亮的逻辑
                        led_2.state = 0;
                        led_9.state = 0;
                    }
                    else
                    {
                        // 死亡
                        led_2.state = !led_2.state;
                        led_2.delay_time = 500;

                        led_9.state = !led_9.state;
                    }
                }
                else
                {
                    // 游戏未开始
                    if (rcsSystem.device.low_batt)
                    {
                        // 低电量警告
                        if (low_battery_count >= 50)
                        {
                            low_battery_count = 0;
                        }
                        if (low_battery_count < 2)
                        {
                            led_2.state = true;
                        }
                        else
                        {
                            led_2.state = false;
                        }
                        led_2.delay_time = 100;
                        low_battery_count++;
                    }
                    else
                    {
                        // 普通情况
                        if (game_no_start_count >= 20)
                        {
                            game_no_start_count = 0;
                        }
                        led_2.state = (game_no_start_count < 10) ? true : false;
                        led_2.delay_time = 100;
                        game_no_start_count++;
                    }
                }
            }
            else
            {
                // 没连接服务器
                if (rcsSystem.device.wait_new_master)
                {
                    // 广播中
                    led_2.state = (advertising_count % 2 == 0) ? true : false;
                    led_2.delay_time = ADVERTISING_INTERVAL;
                    advertising_count++;
                }
                else
                {
                    if (no_connect_count >= 40)
                    {
                        no_connect_count = 0;
                    }
                    led_2.state = (no_connect_count < 10) ? true : false;
                    led_2.delay_time = 100;
                    no_connect_count++;
                }
            }
        }
        set_led_val(LED_2_PIN, led_2.state);
        set_led_val(LED_9_PIN, led_9.state);
        vTaskDelay(pdMS_TO_TICKS(led_2.delay_time));
    }
}

static void nfc_task(void *arg)
{
    if (nfc_init() != ESP_OK)
    {
        ESP_LOGE(NFC_TAG, "nfc_init() != ESP_OK,vTaskDelete");
        rcsSystem.device.is_hold_nfc = false;
        vTaskDelete(NULL);
    }
    rcsSystem.device.is_hold_nfc = true;
    ESP_LOGI(NFC_TAG, "nfc_task Startup..");
    while (1)
    {
        if (rcsSystem.device.is_connect_master == CONNECTED_BLE)
        {
            open_rc522();
            detect_tag();
            // test_add_increase_damage_tag();
            // test_add_increase_hp_tag();
            // test_add_reborn_tag();
            // test_add_increase_bulletnum_tag();
            close_rc522();
            vTaskDelay(pdMS_TO_TICKS(1000));
        }
        else
        {
            ESP_LOGI(BLE_TAG, "didn't connect, so Suspend nfc_task ..");
            vTaskSuspend(NULL);
        }
    }
}
